package gxprod.androidai;

import gxprod.androidai.widgets.Widget;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.media.AudioManager;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.animation.AnimationUtils;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
import android.widget.ViewFlipper;

/**
 * This shouldn't have to mess with this unless the GUI changes or a new way to respond to user input needs to be implemented.
 * @author Josh Maleszewski
 */
public class AIActivity extends Activity implements OnEditorActionListener, OnInitListener, OnClickListener{

	private static Object instance;

	public static final int VOICE_ACTIVITY_ID = 4;
	public static final String TAG = "androidAI";

	public FunctionManager manager;

	public ListView list;
	public EditText input;
	public ImageButton voiceInput;
	public ViewFlipper switcher;

	public BubbleAdapter adapter;

	public boolean TTSReady = false;
	public TextToSpeech mTts;

	public Widget activeWidget;

	@Override
	public void onCreate(Bundle state) {
		super.onCreate(state);
		instance = this;		
		initialize();		
		if(state != null)
			if(state.getBoolean("isPopup", false))
				return;			
		createDefaultGUI();
		initializeSpeech();
		
		super.setVolumeControlStream(AudioManager.STREAM_MUSIC);
	}

	protected void createDefaultGUI() {
		this.requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
		setContentView(R.layout.main);
		setProgressBarIndeterminate(true);

		adapter = new BubbleAdapter(this);

		list 		= (ListView)findViewById(R.id.listView1);
		input 		= (EditText)findViewById(R.id.editText1);
		voiceInput 	= (ImageButton)findViewById(R.id.imageButton1);
		switcher 	= (ViewFlipper)findViewById(R.id.viewFlipper1);

		switcher.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.slide_out_right));
		switcher.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.slide_in_left));
		switcher.setAutoStart(false);

		list.setAdapter(adapter);
		list.setOnItemClickListener(adapter);

		input.setOnEditorActionListener(this);
		voiceInput.setOnClickListener(this);

		if(manager != null)
			manager.Adapter = adapter;
	}

	protected void initializeSpeech() {
		mTts = new TextToSpeech(this, this);

		// If this device doesn't support voice recognition, don't show the voice input button
		PackageManager pm = getPackageManager();
		List<ResolveInfo> activities = pm.queryIntentActivities(new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
		if (activities.size() == 0) 
			Toast.makeText(this, "Text to speech was unable to start. (Do you have any voices installed?)", Toast.LENGTH_LONG).show();
	}

	protected void initialize() {
		if(manager == null)
			manager = new FunctionManager(this);

		DataCollection.loadFromFile(this);
	}

	public boolean onEditorAction(TextView v, int id, KeyEvent e) {
		if(e == null)
			return false;
		if(e.getKeyCode() != KeyEvent.KEYCODE_ENTER)
			return false;
		if(input.getText().toString().equals("") | input.getText().toString().equals("\n"))
			return false;

		String str = new String(input.getText().toString());

		manager.executeVoiceFunction(new Object[] { str });
		adapter.postUpdate();
		input.setText("");
		return true;
	}


	public void onInit(int status) {
		DataCollection.loadFromFile(this);
		if (status == TextToSpeech.SUCCESS) {
			int result = mTts.setLanguage(Locale.US);
			if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) 
				Log.e(TAG, "Language is not available.");
			else 
				TTSReady = true;			
		} else 
			Log.e(TAG, "Could not initialize TextToSpeech.");
	}

	@Override
	public void onDestroy() {
		if (mTts != null) {
			while(mTts.isSpeaking()) 
				Thread.yield();
			mTts.stop();
			mTts.shutdown();
		}
		DataCollection.saveToFile(this);
		super.onDestroy();
	}


	public void onClick(View v) {
		if (v.getId() == R.id.imageButton1) 
			startVoiceRecognitionActivity();
	}


	private void startVoiceRecognitionActivity() {
		Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
		intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, getClass().getPackage().getName());
		intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Say a command or ask a question");
		intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
		intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 10);
		startActivityForResult(intent, VOICE_ACTIVITY_ID);
	}


	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		switch(requestCode) {
			case VOICE_ACTIVITY_ID:
				if (resultCode == RESULT_OK) {
					ArrayList<String> matches = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
					for(int i = 0; i < matches.size(); i++)
						Log.i("Matches", matches.get(i));
					manager.executeVoiceFunction(matches.toArray());
					adapter.postUpdate();
				}
				break;

			default:
				Log.d(TAG, "unrecognised activity return code: " + requestCode);
				break;
		}
	}


	public void TurnOnSpinner() {
		runOnUiThread(new Runnable() {
			public void run(){ setProgressBarIndeterminateVisibility(true); }
		});
	}
	public void TurnOffSpinner() {
		runOnUiThread(new Runnable() {
			public void run(){ setProgressBarIndeterminateVisibility(false); }
		});
	}


	public void onBackPressed() {
		if(manager.Adapter != null) {
			manager.cleanUpOperations();
			if(manager.Operations.size() > 0) {
				for(int i = 0; i < manager.Operations.size(); i++)
					manager.Operations.get(i).cancel();

				manager.Operations.clear();
				Toast.makeText(this, "Background opperations canceled", Toast.LENGTH_SHORT).show();
				return;
			} 
		}
		if(switcher.getChildCount() > 1) {
			closeWidget();
			return;	
		}
		
		super.onBackPressed();
	}

	public static AIActivity get() { return (AIActivity)instance; }

	public void ShowWidget(Widget widget) {
		activeWidget = widget;
		final View v = widget.getTopLevelView();
		if(v == null)
			return;
		runOnUiThread(new Runnable(){ 
			public void run() {
				switcher.addView(v, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
				int i = switcher.getChildCount();
				switcher.showNext();
			}
		});
	}

	public void closeWidget() {
		switcher.removeAllViews();
		switcher.addView(list);
	}
}
